<template>
    <ph-flex :class="cns">
        <div v-if="label" :title="label" class="ph-field-label"><span v-if="required" class="ph-field-rflag">*</span>{{label}}</div>
        <slot></slot>
        <field-tip v-if="invalidTip" :type="labelType">{{invalidTip}}</field-tip>
    </ph-flex>
</template>
<script lang="ts">
import { computed, defineAsyncComponent, defineComponent, inject, onMounted, PropType, ref, Ref, watch } from 'vue'
import { PhFlex } from '../base'
export default defineComponent({
    components:{
        PhFlex,
        FieldTip:defineAsyncComponent(()=>import("./field-tip.vue"))
    },
    props:{
        formStyle:{
            type:String
        },
        label:{
            type:String
        },
        labelType:{
            type:String,
            default:"error"
        },
        validators:{
            type:Array as PropType<Array<string>>
        },
        innerValidators:{
            type:Array as PropType<Array<string>>,
            default:()=>[]
        },
        dirty:{
            type:[String,Number,Boolean,Array]
        },
        block:{
            type:Boolean,
            default:true
        }
    },
    setup(props,{emit,expose}){
        const formStyle = inject("formStyle",) as Ref<string>
        const validation = inject("phValidation") as boolean
        const registerField = inject("registerField") as (vf:()=>Promise<unknown>)=>void
        const validate = inject("phValidate") as (value:unknown, vs:Array<string>)=>Promise<unknown>
        const invalidTip = ref("")
        const invalid = ref(false)
        const required = computed(()=>props.validators&&props.validators.includes("required"))
        const cns = computed(()=>{
            return {
                'ph-field':true,
                'ph-field-block':props.block,
                'ph-field-plain':props.formStyle==="plain"||formStyle.value==="plain",
                'ph-field-invalid':!!invalid.value
            }
        })
        const valid = (v:unknown)=>{
            let validators = [...props.innerValidators]
            if(props.validators&&props.validators.length)
                validators = [...validators,...props.validators]
            if(!validation||!validate||!validators.length) {
                emit('valid',{valid:true,tip:"",v})
                return Promise.resolve({valid:true,tip:""})
            }
            return validate(v,validators)
            .then(()=>{
                console.info(v)
                invalidTip.value=""
                invalid.value = false
                emit('valid',{valid:true,tip:"",v})
                return Promise.resolve({valid:true,tip:""})
            })
            .catch((e)=>{
                console.warn(e)
                invalidTip.value=(e as {tip:string}).tip
                invalid.value = true
                emit('valid',e)
                return Promise.reject(e)
            })
        }
        const customValid = (e:{valid:boolean,tip:string})=>{
            if(!validation){
                invalidTip.value = e.tip;
                invalid.value = !e.valid
            }
        }
        watch(()=>props.dirty,(v:unknown,o:unknown)=>{
            if(v!==o) valid(v)
        })
        onMounted(()=>{
            if(validation)
            registerField(()=>{
                return valid(props.dirty)
            })
        })
        expose({
            customValid
        })
        
        return {
            required,
            cns,
            invalidTip,
        }
    }
})
</script>

<style lang="scss">
@import '../../assets/scss/predef.scss';
.ph-field{
    flex-wrap: wrap;
    margin-bottom:  var(--ph-30);
    color: var(--ph-c);
    align-items: center;
    flex: 1 0 auto;
    width: auto;
    font-size: var(--phx);
    &-block{
        flex: 0 0 auto;
        width: 100%;
    }
    &-rflag{
        color: var(--ph-danger);
        padding: 0 var(--ph-5);
    }
    
    &-invalid{
        &:after,
        .ph-textarea,
        .ph-btn-color,
        .ph-btn-datetime,
        .ph-input,
        .ph-input-divider{
            border-bottom-color: var(--ph-danger)!important;
        }
    }
    &-label{
        flex: 0 0 auto;
        text-align: right;
        color: var(--ph-c-d1);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
}

@media screen and (max-width: 768px) {
    .ph-field{
        width: 100%;
        flex: 0 0 auto;
        .ph-input-wrap{
            width: 100%;
            flex: 0 0 auto;
        }
        &-label{
            width: 100%;
            text-align: left;
            padding: 0 0 var(--ph-form-vpadding) 0;
        }
    }
}

@media screen and (min-width: 769px) {
    .ph-field{
        --ph-label-width: calc(var(--phx) * 7.8571);
        &-label{
            width: var(--ph-label-width);
            padding: var(--ph-form-vpadding) var(--ph-10);
        }
        &-plain{
            .ph-field-label{
                background-color: var(--ph-light-l1);
                border: 1px solid var(--ph-form-border);
                border-radius: var(--ph-form-radius) 0 0 var(--ph-form-radius);
                text-align: center;
            }
            
            .ph-input{
                border-top-left-radius:0!important;
                border-bottom-left-radius: 0!important;
                margin-left: -1px;
            }
        }
        &-multilines.ph-field-plain{
            justify-content: space-between;
            align-items: center;
            border-radius: var(--ph-form-radius) 0 0 var(--ph-form-radius);
            padding-right: var(--ph-10);
            &:before,
            &:after{
                content: "";
                position: absolute;
                height: 100%;
                top:0;
                border:1px solid var(--ph-form-border);
            }
            &:before{
                width: var(--ph-label-width);;
                left: 0;
                background-color: var(--ph-light-l1);
            }
            &:after{
                left: var(--ph-label-width);;
                right: 0;
                margin-left: -1px;
            }
            .ph-field-label{
                background-color: transparent;
                border: 1px solid transparent;
                position: relative;
                z-index: 1;
            }
        }
    }
}
</style>